﻿namespace MefContrib.Models.Provider.Tests
{
    using System;
    using System.Reflection;
    using NUnit.Framework;
    using System.ComponentModel.Composition.Primitives;
    using System.Collections.Generic;

    [TestFixture]
    public class ComposableMemberTests
    {
        [Test]
        public void SingleImportGetsSatisfied()
        {
            var member = 
                typeof(DummyPart).GetMember("DummyImport");
            
            var composable = 
                member[0].ToComposableMember();

            var e = new Export("System.String",() => "bar");

            var value = 
                composable.GetImportValueFromExports(new List<Export> { e });

            Assert.AreEqual("bar", value);
        }

        [Test]
        public void SingleLazyImportGetsSatisfied()
        {
            var member =
                typeof(DummyPart).GetMember("DummyLazyImport");

            var composable =
                member[0].ToComposableMember();

            var e = new Export("System.String", () => "bar");

            var value =
                (Lazy<string>)composable.GetImportValueFromExports(new List<Export> { e });

            Assert.AreEqual(e.Value, value.Value);
        }

        [Test]
        public void CollectionImportGetsSatisfied()
        {
            var member =
                typeof (DummyPart).GetMember("DummyCollectionImport");

            var composable =
                member[0].ToComposableMember();

            var e = new List<Export>
            {
                new Export("System.String", () => "bar")
            };

            var value = (List<string>)
                composable.GetImportValueFromExports(e);

            Assert.AreEqual(1, value.Count);
            Assert.AreEqual("bar", value[0]);
        }

        [Test]
        public void LazyCollectionImportGetsSatisfied()
        {
            var member =
                typeof(DummyPart).GetMember("DummyLazyCollectionImport");

            var composable =
                member[0].ToComposableMember();

            var e = new List<Export>
            {
                new Export("System.String", () => "bar")
            };

            var value = (List<Lazy<string>>)
                composable.GetImportValueFromExports(e);

            Assert.AreEqual(1, value.Count);
            Assert.AreEqual(e[0].Value, value[0].Value);

        }

        [Test]
        public void LazyMetadataCollectionImportGetsSatisfied()
        {
            var member =
                typeof(DummyPart).GetMember("DummyLazyMetadataCollectionImport");

            var composable =
                member[0].ToComposableMember();

            var metadata = new Dictionary<string, object>();
            metadata.Add("Name", "foo");
            var e = new List<Export>
            {
                new Export("System.String", metadata, () => "bar")
            };

            var value = (List<Lazy<string,IDummyView>>)
                composable.GetImportValueFromExports(e);

            Assert.AreEqual(1, value.Count);
            Assert.AreEqual(e[0].Value, value[0].Value);
            Assert.AreEqual("foo", value[0].Metadata.Name);
        }


        [Test]
        public void CreateShouldReturnComposableFieldInstanceForFieldMember()
        {
            ComposableMember composable =
                ComposableMember.Create(typeof(FakeFieldPart).GetMember("plainField")[0]);

            Assert.IsTrue(composable.GetType() == typeof(ComposableField));
        }

        [Test]
        public void CreateShouldReturnComposablePropertyInstanceForPropertyMember()
        {
            ComposableMember composable =
                ComposableMember.Create(typeof(FakePropertyPart).GetMember("NonStaticReadWrite")[0]);

            Assert.IsTrue(composable.GetType() == typeof(ComposableProperty));
        }

        [Test]
        public void CreateShouldReturnComposableMethodInstanceForMethodMember()
        {
            ComposableMember composable =
                ComposableMember.Create(typeof(FakeMethodPart).GetMember("NoReturnNoParameters")[0]);

            Assert.IsTrue(composable.GetType() == typeof(ComposableMethod));
        }

        [Test]
        public void CreateShouldReturnComposableTypeInstanceForClass()
        {
            ComposableMember composable =
                ComposableMember.Create(typeof(FakePart));

            Assert.IsTrue(composable.GetType() == typeof(ComposableType));
        }

        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void CreateShouldThrowExceptionIfPassedNull()
        {
            ComposableMember composable =
                ComposableMember.Create(null);
        }
    }
}